
(function ($, win, doc, body) {
    var supportedClient = true,
        jqTemplateId = "jqTemplateStatusbox",
        openedClassname = "tl-statusbox-opened",
        selecteditemClassname = "tl-statusbox-selected-item",
        disabledClassname = "disabled",
        $body = $(body);

    // check client
    supportedClient = true;

    // callbacks
    function onBodyClick (evt) {
        $body.unbind("click", onBodyClick).find("div." + openedClassname)
          .removeClass(openedClassname).find("div.statusbox-container").hide();
    }

    function onSelectFocus (evt) {
        var $select = $(evt && evt.target ? evt.target : null),
            $statusbox = $select.parents("div.custom-statusbox:first");

        $statusbox.find("span.statusbox-title:first").trigger("click");
    }

    function onSelectBlur (evt) {
        onBodyClick();
    }

    function onSelectChange (evt) {
        var $select = $(evt && evt.target ? evt.target : null),
            $statusbox = $select.parents("div.custom-statusbox:first"),
            $items = $statusbox.find("li.statusbox-item"),
            item = null,
            oldselecteditem = null,
            selecteditem = null,
            itemsInd = $items.length,
            classname = "",
            classnames = null,
            classnamesInd = 0,
            value = $select.val();

        while (itemsInd--) {
            item = $items[itemsInd];
            if (value == item.getAttribute("data-value")) {
                selecteditem = item;
            }

            if (item.className.indexOf(selecteditemClassname) !== -1) {
                classnames = item.className.split(/\s+/);
                classnamesInd = classnames.length;
                while (classnamesInd--) {
                    classname = classnames[classnamesInd];
                    $statusbox.removeClass(classname);
                    if (classname === selecteditemClassname) {
                        classnames.splice(classnamesInd, 1);
                    }
                }
                item.className = classnames.join(" ");
            }
        }

        if (selecteditem) {
            $statusbox.addClass(selecteditem.className);
            selecteditem.className += " " + selecteditemClassname;
        }
    }

    function onTitleClick (evt) {
        onBodyClick();
        var $statusbox = $(this).parents("div.custom-statusbox:first");

        if ($statusbox.hasClass(openedClassname) || $statusbox.hasClass(disabledClassname)) {
          return undefined;
        }

        $statusbox.addClass(openedClassname).find("div.statusbox-container:first").show();
        setTimeout(bindBodyEvents, 0);
    }

    function onOptionClick (evt) {
        var $target = $(evt && evt.target ? evt.target : null);
        $target.length > 0 && ($target = $target.is("li.statusbox-item") ? $target : $target.parent("li.statusbox-item"));

        if ($target.is("li.statusbox-item")) {
            var value = $target.attr("data-value");
            $target.parents("div.custom-statusbox:first").find("select").val(value).change();
        }
    }

    function bindBodyEvents () {
        $body.bind("click", onBodyClick);
    }

    function bindEvents ($select, $statusbox) {
        $select
          .unbind("focus", onSelectFocus).bind("focus", onSelectFocus)
          .unbind("blur", onSelectBlur).bind("blur", onSelectBlur)
          .unbind("change", onSelectChange).bind("change", onSelectChange);

        $statusbox.find("span.statusbox-title:first")
          .unbind("click", onTitleClick).bind("click", onTitleClick);

        $statusbox.find("ul.statusbox-list:first")
          .unbind("click", onOptionClick).bind("click", onOptionClick);
    }

    function initStatusbox ($select, opt) {
        var $statusbox,
            selectedValue = $select.val(),
            data = {
                classname: $select.attr("class"),
                value: "",
                title: "",
                options: []
            };

        var optionValue = "",
            optionTitle = "",
            optionClassname = "",
            option = null,
            $options = $select.find("option"),
            optionsInd = $options.length;
        while (optionsInd--) {
            option = $options[optionsInd];
            optionValue = option.getAttribute("value");
            optionTitle = option.innerHTML;
            optionClassname = (option.getAttribute("class") || "").toLowerCase();
            if (selectedValue == optionValue) {
                data.value = optionValue;
                data.title = optionTitle;
                optionClassname ? data.classname += " " + optionClassname : null;
                optionClassname += (optionClassname ? " " : "") + selecteditemClassname;
            }
            data.options.unshift({
                classname: optionClassname,
                value: optionValue,
                title: optionTitle
            });
        }

        if ($select.is(":disabled")) {
          data.classname += (data.classname ? " " : "") + "disabled";
        }

        $statusbox = $.tlTmpl(jqTemplateId, data);
        $select.before($statusbox);
        $statusbox.append($select);

        bindEvents($select, $statusbox);
    }

    $.fn.tlStatusbox = function (opt) {
        opt = $.extend({
            // default options
        }, opt);

        return this.each(function () {
            var $this = $(this);
            if (supportedClient && $this.is("select")) {
                initStatusbox($this, opt);
            }
        });
    };
})(jQuery, window, document, document.body);
